﻿using CommandLine;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Software_upgrade_Form
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        #region 文件操作相关方法

        /// <summary>
        /// 传入的参数列表
        /// </summary>
        public List<string> argss { get; set; } = new List<string>();

        /// <summary>
        /// 拷贝ZIP文件（带进度显示）
        /// </summary>
        /// <param name="SouFilePath">源文件路径</param>
        /// <param name="CopyPath">目标文件路径</param>
        /// <param name="progressCallback">进度回调函数</param>
        /// <returns>拷贝是否成功</returns>
        public bool CopyZipFile(string SouFilePath, string CopyPath, Action<string, int> progressCallback = null)
        {
            bool success = false;
            FileStream sourceStream = null;
            FileStream destinationStream = null;

            try
            {
                progressCallback?.Invoke("开始拷贝ZIP文件...", 0);
                Logger.Info($"拷贝ZIP文件从: {SouFilePath}");
                Logger.Info($"拷贝ZIP文件到: {CopyPath}");

                string directoryName = Path.GetDirectoryName(CopyPath);
                string fileNameWithExtension = Path.GetFileName(CopyPath);

                // 确保目标目录存在
                if (!Directory.Exists(directoryName))
                {
                    Directory.CreateDirectory(directoryName);
                    Logger.Info($"创建目标目录:{directoryName}");
                }

                // 检查源文件是否存在
                if (!File.Exists(SouFilePath))
                {
                    Logger.Error($"源文件不存在: {SouFilePath}");
                    throw new FileNotFoundException($"源文件不存在: {SouFilePath}");
                }

                // 如果目标文件已存在，先删除
                if (File.Exists(CopyPath))
                {
                    File.Delete(CopyPath);
                    Logger.Info("删除已存在的目标文件");
                }

                // 获取文件信息
                FileInfo sourceFileInfo = new FileInfo(SouFilePath);
                long fileSize = sourceFileInfo.Length;
                Logger.Info($"文件大小: {fileSize} bytes ({FormatFileSize(fileSize)})");

                progressCallback?.Invoke("准备文件流...", 5);

                // 创建文件流
                sourceStream = new FileStream(SouFilePath, FileMode.Open, FileAccess.Read);
                destinationStream = new FileStream(CopyPath, FileMode.Create, FileAccess.Write);

                // 设置缓冲区大小（可根据需要调整）
                int bufferSize = 1024 * 1024; // 1MB
                byte[] buffer = new byte[bufferSize];
                long totalBytesRead = 0;
                int bytesRead;

                progressCallback?.Invoke("开始拷贝数据...", 10);

                // 分块读取和写入文件
                while ((bytesRead = sourceStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    destinationStream.Write(buffer, 0, bytesRead);
                    totalBytesRead += bytesRead;

                    // 计算进度百分比
                    int progress = fileSize > 0 ? (int)((double)totalBytesRead / fileSize * 100) : 0;
                    progress = Math.Min(progress, 100); // 确保不超过100%

                    // 更新进度
                    string progressMessage = $"拷贝文件中... {FormatFileSize(totalBytesRead)} / {FormatFileSize(fileSize)}";
                    progressCallback?.Invoke(progressMessage, progress);

                    // 可选：添加小延迟以便观察进度（对于大文件）
                    // Thread.Sleep(1);
                }

                progressCallback?.Invoke("文件拷贝完成，验证中...", 95);

                // 刷新并关闭流
                destinationStream.Flush();
                sourceStream.Close();
                destinationStream.Close();

                // 验证拷贝的文件
                FileInfo copiedFile = new FileInfo(CopyPath);
                if (copiedFile.Exists && copiedFile.Length == fileSize)
                {
                    Logger.Info($"拷贝验证成功，文件大小: {copiedFile.Length} bytes");
                    progressCallback?.Invoke("ZIP文件拷贝完成", 100);
                    success = true;
                }
                else
                {
                    throw new Exception("文件拷贝验证失败，大小不匹配");
                }
            }
            catch (Exception ex)
            {
                Logger.Error($"拷贝失败: {ex.Message}");
                progressCallback?.Invoke($"拷贝失败: {ex.Message}", 0);
                throw new Exception($"拷贝文件失败: {ex.Message}", ex);
            }
            finally
            {
                // 确保流被关闭
                sourceStream?.Close();
                destinationStream?.Close();
            }

            return success;
        }

        /// <summary>
        /// 格式化文件大小显示（B/KB/MB/GB）
        /// </summary>
        /// <param name="bytes">文件大小（字节）</param>
        /// <returns>格式化后的文件大小字符串</returns>
        private string FormatFileSize(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB" };
            int order = 0;
            double len = bytes;
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len = len / 1024;
            }
            return $"{len:0.##} {sizes[order]}";
        }

        /// <summary>
        /// 解压ZIP文件（带进度显示）
        /// </summary>
        /// <param name="zipPath">ZIP文件路径</param>
        /// <param name="extractPath">解压目标路径</param>
        /// <param name="progressCallback">进度回调函数</param>
        private void ExtractZipWithProgress(string zipPath, string extractPath, Action<string, int> progressCallback = null)
        {
            try
            {
                progressCallback?.Invoke("准备解压环境...", 0);

                // 确保解压目录存在且为空
                if (!Directory.Exists(extractPath))
                {
                    Directory.CreateDirectory(extractPath);
                }
                else
                {
                    Directory.Delete(extractPath, true);
                    Thread.Sleep(100);
                    Directory.CreateDirectory(extractPath);
                }

                progressCallback?.Invoke("正在解压ZIP文件...", 30);

                // 解压ZIP文件
                ZipFile.ExtractToDirectory(zipPath, extractPath);

                progressCallback?.Invoke("ZIP文件解压完成", 100);
                Logger.Info("ZIP文件解压完成");
            }
            catch (Exception ex)
            {
                progressCallback?.Invoke($"解压失败: {ex.Message}", 0);
                throw new Exception($"解压文件失败: {ex.Message}", ex);
            }
        }

        /// <summary>
        /// 拷贝目录及其所有子目录和文件（带进度显示）
        /// </summary>
        /// <param name="sourceDir">源目录路径</param>
        /// <param name="targetDir">目标目录路径</param>
        /// <param name="progressCallback">进度回调函数</param>
        public static void CopyDirectoryWithProgress(string sourceDir, string targetDir, Action<string, int> progressCallback = null)
        {
            try
            {
                progressCallback?.Invoke("正在扫描文件...", 0);

                // 获取所有文件（包括子目录）
                string[] allFiles = Directory.GetFiles(sourceDir, "*.*", SearchOption.AllDirectories);
                int totalFiles = allFiles.Length;
                int processedFiles = 0;

                Logger.Info($"开始拷贝目录，共 {totalFiles} 个文件");

                // 创建目标目录
                Directory.CreateDirectory(targetDir);

                foreach (string file in allFiles)
                {
                    // 计算相对路径
                    string relativePath = GetRelativePath(sourceDir, file);
                    string destFile = Path.Combine(targetDir, relativePath);

                    // 确保目标目录存在
                    string destDir = Path.GetDirectoryName(destFile);
                    Directory.CreateDirectory(destDir);

                    // 拷贝文件（覆盖已存在的）
                    File.Copy(file, destFile, true);

                    processedFiles++;

                    // 计算进度
                    int progress = totalFiles > 0 ? (int)((double)processedFiles / totalFiles * 100) : 100;
                    progressCallback?.Invoke($"拷贝文件:{relativePath}到:{destFile}", progress);

                    Logger.Info($"[{processedFiles}/{totalFiles}] {relativePath}");
                }

                progressCallback?.Invoke("目录拷贝完成", 100);
                Logger.Info($"目录拷贝完成，共处理 {processedFiles} 个文件");
            }
            catch (Exception ex)
            {
                progressCallback?.Invoke($"拷贝失败: {ex.Message}", 0);
                Logger.Error($"拷贝目录失败: {ex.Message}");
                throw;
            }
        }

        /// <summary>
        /// 获取相对路径
        /// </summary>
        /// <param name="basePath">基础路径</param>
        /// <param name="fullPath">完整路径</param>
        /// <returns>相对路径</returns>
        private static string GetRelativePath(string basePath, string fullPath)
        {
            if (!basePath.EndsWith(Path.DirectorySeparatorChar.ToString()))
                basePath += Path.DirectorySeparatorChar;

            Uri baseUri = new Uri(basePath);
            Uri fullUri = new Uri(fullPath);

            return Uri.UnescapeDataString(baseUri.MakeRelativeUri(fullUri).ToString().Replace('/', Path.DirectorySeparatorChar));
        }
        /// <summary>
        /// 处理命令行选项（主处理函数 - 新版本，带延迟关闭）
        /// </summary>
        /// <param name="options">命令行选项</param>
        private void ProcessCommandLineOptions(CommandLineOptions options)
        {
            // 使用标记方式获取值
            string FileName = options.FileName;
            string FilePath = options.FilePath;
            string Version = options.Version;

            // 输出参数信息
            Logger.Info("解析后的参数:");
            Logger.Info($"FileName: {FileName}");
            Logger.Info($"FilePath: {FilePath}");
            Logger.Info($"Version: {Version}");

            // 更新界面显示
            FileName_text.Text = FileName;
            Ver_lab.Text = Version;

            // 根据参数执行操作
            if (!string.IsNullOrEmpty(FileName) && !string.IsNullOrEmpty(FilePath))
            {
                try
                {
                    string currentDir = Directory.GetCurrentDirectory();
                    // 获取当前目录的上一层目录
                    string parentDir = Directory.GetParent(currentDir).FullName;

                    Logger.Info($"当前目录: {currentDir}");
                    Logger.Info($"上一层目录: {parentDir}");

                    string copyDir = Path.Combine(currentDir, "Copy");
                    string zipPath = Path.Combine(copyDir, "Copy.zip");
                    string extractDir = Path.Combine(currentDir, "ExtractToDirectory");
                    string targetDir = parentDir; // 解压到上一层目录

                    // 阶段1: 拷贝ZIP文件 (0-25%)
                    UpdateProgress("正在拷贝ZIP文件...", 0);
                    CopyZipFile(FilePath, zipPath, UpdateProgress);

                    // 阶段2: 解压ZIP文件 (25-50%)
                    UpdateProgress("正在解压ZIP文件...", 25);
                    ExtractZipWithProgress(zipPath, extractDir, (msg, progress) =>
                    {
                        // 将解压进度映射到25-50%范围
                        int mappedProgress = 25 + (int)(progress * 0.25);
                        UpdateProgress(msg, mappedProgress);
                    });

                    // 阶段3: 拷贝解压的文件到上一层目录 (50-100%)
                    UpdateProgress("正在拷贝解压文件到上一层目录...", 50);
                    CopyDirectoryWithProgress(extractDir, targetDir, (msg, progress) =>
                    {
                        // 将拷贝进度映射到50-100%范围
                        int mappedProgress = 50 + (int)(progress * 0.5);
                        UpdateProgress(msg, mappedProgress);
                    });

                    UpdateProgress("所有操作完成！", 100);

                    // 显示完成消息，然后延迟关闭
                    MessageBox.Show($"文件处理完成！文件已拷贝到目录: {parentDir}\n程序将在3秒后自动关闭。", "成功",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);

                    // 延迟3秒后关闭，让用户看到完成状态
                    Task.Delay(3000).ContinueWith(t => {
                        if (this.InvokeRequired)
                        {
                            this.Invoke(new Action(() => this.Close()));
                        }
                        else
                        {
                            this.Close();
                        }
                    });
                }
                catch (Exception ex)
                {
                    UpdateProgress($"处理失败: {ex.Message}", 0);
                    MessageBox.Show($"处理失败: {ex.Message}", "错误",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);

                    // 出错时也延迟关闭
                    Task.Delay(3000).ContinueWith(t => {
                        if (this.InvokeRequired)
                        {
                            this.Invoke(new Action(() => this.Close()));
                        }
                        else
                        {
                            this.Close();
                        }
                    });
                }
            }
            else
            {
                // 参数无效时也关闭
                MessageBox.Show("参数无效，程序将关闭。", "错误",
                    MessageBoxButtons.OK, MessageBoxIcon.Warning);
                this.Close();
            }
        }
        /// <summary>
        /// 处理命令行选项（主处理函数 - 新版本，带延迟关闭）
        /// </summary>
        /// <param name="options">命令行选项</param>
        private void ProcessCommandLineOptions3(CommandLineOptions options)
        {
            // 使用标记方式获取值
            string FileName = options.FileName;
            string FilePath = options.FilePath;
            string Version = options.Version;

            // 输出参数信息
            Logger.Info("解析后的参数:");
            Logger.Info($"FileName: {FileName}");
            Logger.Info($"FilePath: {FilePath}");
            Logger.Info($"Version: {Version}");

            // 更新界面显示
            FileName_text.Text = FileName;
            Ver_lab.Text = Version;

            // 根据参数执行操作
            if (!string.IsNullOrEmpty(FileName) && !string.IsNullOrEmpty(FilePath))
            {
                try
                {
                    string currentDir = Directory.GetCurrentDirectory();
                    string copyDir = Path.Combine(currentDir, "Copy");
                    string zipPath = Path.Combine(copyDir, "Copy.zip");
                    string extractDir = Path.Combine(currentDir, "ExtractToDirectory");
                    string targetDir = currentDir; // 解压到当前目录

                    // 阶段1: 拷贝ZIP文件 (0-25%)
                    UpdateProgress("正在拷贝ZIP文件...", 0);
                    CopyZipFile(FilePath, zipPath, UpdateProgress);

                    // 阶段2: 解压ZIP文件 (25-50%)
                    UpdateProgress("正在解压ZIP文件...", 25);
                    ExtractZipWithProgress(zipPath, extractDir, (msg, progress) =>
                    {
                        // 将解压进度映射到25-50%范围
                        int mappedProgress = 25 + (int)(progress * 0.25);
                        UpdateProgress(msg, mappedProgress);
                    });

                    // 阶段3: 拷贝解压的文件 (50-100%)
                    UpdateProgress("正在拷贝解压文件...", 50);
                    CopyDirectoryWithProgress(extractDir, targetDir, (msg, progress) =>
                    {
                        // 将拷贝进度映射到50-100%范围
                        int mappedProgress = 50 + (int)(progress * 0.5);
                        UpdateProgress(msg, mappedProgress);
                    });

                    UpdateProgress("所有操作完成！", 100);

                    // 显示完成消息，然后延迟关闭
                    MessageBox.Show("文件处理完成！程序将在3秒后自动关闭。", "成功",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);

                    // 延迟3秒后关闭，让用户看到完成状态
                    Task.Delay(3000).ContinueWith(t => {
                        if (this.InvokeRequired)
                        {
                            this.Invoke(new Action(() => this.Close()));
                        }
                        else
                        {
                            this.Close();
                        }
                    });
                }
                catch (Exception ex)
                {
                    UpdateProgress($"处理失败: {ex.Message}", 0);
                    MessageBox.Show($"处理失败: {ex.Message}", "错误",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);

                    // 出错时也延迟关闭
                    Task.Delay(3000).ContinueWith(t => {
                        if (this.InvokeRequired)
                        {
                            this.Invoke(new Action(() => this.Close()));
                        }
                        else
                        {
                            this.Close();
                        }
                    });
                }
            }
            else
            {
                // 参数无效时也关闭
                MessageBox.Show("参数无效，程序将关闭。", "错误",
                    MessageBoxButtons.OK, MessageBoxIcon.Warning);
                this.Close();
            }
        }

        /// <summary>
        /// 主处理函数（旧版本，立即关闭）
        /// </summary>
        /// <param name="options">命令行选项</param>
        private void ProcessCommandLineOptions2(CommandLineOptions options)
        {
            // 使用标记方式获取值
            string FileName = options.FileName;
            string FilePath = options.FilePath;
            string Version = options.Version;

            // 输出参数信息
            Logger.Info("解析后的参数:");
            Logger.Info($"FileName: {FileName}");
            Logger.Info($"FilePath: {FilePath}");
            Logger.Info($"Version: {Version}");
            FileName_text.Text = FileName;

            // 根据参数执行操作
            if (!string.IsNullOrEmpty(FileName) && !string.IsNullOrEmpty(FilePath))
            {
                try
                {
                    string currentDir = Directory.GetCurrentDirectory();
                    string copyDir = Path.Combine(currentDir, "Copy");
                    string zipPath = Path.Combine(copyDir, "Copy.zip");
                    string extractDir = Path.Combine(currentDir, "ExtractToDirectory");
                    string targetDir = currentDir; // 解压到当前目录

                    // 阶段1: 拷贝ZIP文件 (0-25%)
                    UpdateProgress("正在拷贝ZIP文件...", 0);
                    CopyZipFile(FilePath, zipPath, UpdateProgress);

                    // 阶段2: 解压ZIP文件 (25-50%)
                    UpdateProgress("正在解压ZIP文件...", 25);
                    ExtractZipWithProgress(zipPath, extractDir, (msg, progress) =>
                    {
                        // 将解压进度映射到25-50%范围
                        int mappedProgress = 25 + (int)(progress * 0.25);
                        UpdateProgress(msg, mappedProgress);
                    });

                    // 阶段3: 拷贝解压的文件 (50-100%)
                    UpdateProgress("正在拷贝解压文件...", 50);
                    CopyDirectoryWithProgress(extractDir, targetDir, (msg, progress) =>
                    {
                        // 将拷贝进度映射到50-100%范围
                        int mappedProgress = 50 + (int)(progress * 0.5);
                        UpdateProgress(msg, mappedProgress);
                    });

                    UpdateProgress("所有操作完成！", 100);
                    MessageBox.Show("文件处理完成！", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    this.Close();
                }
                catch (Exception ex)
                {
                    UpdateProgress($"处理失败: {ex.Message}", 0);
                    MessageBox.Show($"处理失败: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        /// <summary>
        /// 显示复制后的文件列表
        /// </summary>
        /// <param name="directoryPath">目录路径</param>
        private void DisplayCopiedFiles(string directoryPath)
        {
            try
            {
                var files = Directory.GetFiles(directoryPath, "*.*", SearchOption.AllDirectories);
                var directories = Directory.GetDirectories(directoryPath, "*", SearchOption.AllDirectories);

                Logger.Info($"复制完成！共 {files.Length} 个文件，{directories.Length + 1} 个目录");
                Logger.Info("复制的文件列表:");

                foreach (string file in files)
                {
                    string relativePath = GetRelativePath(directoryPath, file);
                    FileInfo fileInfo = new FileInfo(file);
                    Logger.Info($"  {relativePath} ({fileInfo.Length} bytes)");
                }
            }
            catch (Exception ex)
            {
                Logger.Error($"显示文件列表时出错: {ex.Message}");
            }
        }

        /// <summary>
        /// 拷贝文件和目录（递归方式）
        /// </summary>
        /// <param name="sourceDir">源目录</param>
        /// <param name="targetDir">目标目录</param>
        public static void CopyDirectory(string sourceDir, string targetDir)
        {
            try
            {
                // 创建目标目录
                Directory.CreateDirectory(targetDir);

                // 拷贝所有文件
                foreach (string file in Directory.GetFiles(sourceDir))
                {
                    string fileName = Path.GetFileName(file);
                    string destFile = Path.Combine(targetDir, fileName);
                    File.Copy(file, destFile, true); // true表示覆盖已存在的文件
                    Logger.Info($"拷贝文件: {fileName}");
                }

                // 递归拷贝所有子目录
                foreach (string directory in Directory.GetDirectories(sourceDir))
                {
                    string dirName = Path.GetFileName(directory);
                    string destDir = Path.Combine(targetDir, dirName);
                    CopyDirectory(directory, destDir);
                }
            }
            catch (Exception ex)
            {
                Logger.Error($"拷贝目录失败: {ex.Message}");
                throw;
            }
        }

        /// <summary>
        /// 更新进度显示
        /// </summary>
        /// <param name="message">进度消息</param>
        /// <param name="progress">进度百分比</param>
        private void UpdateProgress(string message, int progress)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new Action<string, int>(UpdateProgress), message, progress);
                return;
            }
            Logger.Info(message);
            statusLabel.Text = message;
            progressBar.Value = progress;
            Application.DoEvents(); // 确保UI更新
        }
        #endregion

        #region 窗体事件处理

        /// <summary>
        /// 窗体显示事件
        /// </summary>
        private void Form1_Shown(object sender, EventArgs e)
        {
            // 接收命令
            if (argss != null && argss.Count > 0)
            {
                Logger.Info("原始参数: " + string.Join(", ", argss));
                // 使用CommandLineParser解析参数
                var parserResult = Parser.Default.ParseArguments<CommandLineOptions>(argss);

                parserResult
                    .WithParsed<CommandLineOptions>(options =>
                    {
                        // 解析成功，处理参数
                        ProcessCommandLineOptions(options);
                    })
                    .WithNotParsed<CommandLineOptions>(errors =>
                    {
                        // 解析失败，显示错误
                        string errorMessage = "命令行参数解析错误:\n";
                        foreach (var error in errors)
                        {
                            errorMessage += $"- {error}\n";
                        }
                        Logger.Error(errorMessage);
                        MessageBox.Show(errorMessage, "参数错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    });
            }
            else
            {
                // 如果没有命令行参数，显示错误并关闭
                Logger.Error("命令错误");
                MessageBox.Show("命令错误!", "提示");
                this.Close();
            }
        }

        /// <summary>
        /// 窗体加载事件
        /// </summary>
        private void Form1_Load(object sender, EventArgs e)
        {
            // 窗体加载时的初始化代码可以放在这里
        }
        #endregion
    }

    /// <summary>
    /// 命令行选项类
    /// 用于定义和解析命令行参数
    /// </summary>
    public class CommandLineOptions
    {
        [Option('n', "FileName", HelpText = "文件名称")]
        public string FileName { get; set; }

        [Option('p', "FilePath", HelpText = "文件路径")]
        public string FilePath { get; set; }

        [Option('v', "Version", HelpText = "版本")]
        public string Version { get; set; }

        [Value(0, HelpText = "输入文件", MetaName = "InputFile")]
        public string InputFile { get; set; }
    }
}